#include <iostream>
#include <thread>
#include <future>
#include <memory>

/*
    packaged_task是一个模板类，实例化的对象可以对一个函数进行二次封装
    可以通过get_future获取一个future对象，来获取封装的这个函数的异步执行结果
*/

int Add(int num1, int num2){
    std::cout << "-----------add执行中-----------\n";
    std::this_thread::sleep_for(std::chrono::seconds(3));
    std::cout << "-----------add执行完-----------\n";
    return num1 + num2;
}

int main(){
    //std::packaged_task<int(int, int)> task(Add);
    //std::future<int> fu = task.get_future();
    /*
        task可以当作一个可调用对象来调用执行任务：task(11,22)
        但是又不能完全当作一个函数来使用：
        std::async(std::launch::async, task, 11, 22);err
        std::thread thr(task, 11, 22);err

        我们可以把task定义成一个指针，传递到线程中，然后进行解引用执行,
        但是如果单纯指针指向一个对象，存在生命周期的问题，很有可能出现风险
        思想就是在堆上new对象，用智能呢个指针管理它的生命周期
    */

    auto ptask = std::make_shared<std::packaged_task<int(int, int)>>(Add);
    std::future<int> fu = ptask->get_future();

    std::thread thr([ptask](){// lambda
        (*ptask)(11, 22);
    });
    std::this_thread::sleep_for(std::chrono::seconds(3));
    std::cout << "----------main线程休眠完----------\n";//conclusion:一旦把任务发放给工作线程，工作线程立马执行（有的测试代码现象偶尔不符合是因为调度的问题）
    int sum = fu.get();
    std::cout << sum << std::endl;

    thr.join();
    return  0;
}